package com.heima.admin.service.impl;
import java.util.Date;

import com.alibaba.fastjson.JSONArray;
import com.heima.admin.feign.ArticleFeign;
import com.heima.admin.feign.WemediaFeign;
import com.heima.admin.mapper.AdChannelMapper;
import com.heima.admin.mapper.AdSensitiveMapper;
import com.heima.admin.service.WemediaNewsAutoScanService;
import com.heima.common.aliyun.GreenImageScan;
import com.heima.common.aliyun.GreenTextScan;
import com.heima.common.constants.message.ArticleForEsConstants;
import com.heima.common.constants.user.admin.AuthConstants;
import com.heima.common.fastdfs.FastDFSClient;
import com.heima.model.admin.pojos.AdChannel;
import com.heima.model.article.pojos.ApArticle;
import com.heima.model.article.pojos.ApArticleConfig;
import com.heima.model.article.pojos.ApArticleContent;
import com.heima.model.article.pojos.ApAuthor;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.media.dtos.NewsAuthDto;
import com.heima.model.media.pojos.WmNews;
import com.heima.model.media.pojos.WmUser;
import com.heima.model.media.vo.WmNewsVo;
import com.heima.utils.common.SensitiveWordUtil;
import io.seata.common.util.StringUtils;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.util.*;

@Service
@Log4j2
public class WemediaNewsAutoScanServiceImpl implements WemediaNewsAutoScanService {
    @Autowired
    private WemediaFeign wemediaFeign;
    @Autowired
    private ArticleFeign articleFeign;
    @Autowired
    private GreenImageScan greenImageScan;
    @Autowired
    private GreenTextScan greenTextScan;
    @Autowired
    private FastDFSClient fastDFSClient;

    @Autowired
    private AdSensitiveMapper adSensitiveMapper;
    @Autowired
    private AdChannelMapper adChannelMapper;
    @Value("${fdfs.url}")
    private String url;

    @Autowired
    private KafkaTemplate<String,String> kafkaTemplate;


    //kafka消费者方法调用，自动审核和发布文章
    @Override
    //@GlobalTransactional
    public void autoScanByMediaNewsId(Integer id) {
        if (id == null) {
            log.error("文章id为空");
            return;
        }
        WmNews wmNews = wemediaFeign.findById(id);
        if (wmNews == null){
            log.error("没有与id={}对应的文章",id);
            return;
        }
        //如果status为4或8
        if (    (WmNews.Status.ADMIN_SUCCESS.getCode().equals(wmNews.getStatus())
                || WmNews.Status.SUCCESS.getCode().equals(wmNews.getStatus()))
                && System.currentTimeMillis()>=wmNews.getPublishTime().getTime()
        ){
            saveAppArticle(wmNews);
            return;
        }

        //如果status为1
        if (WmNews.Status.SUBMIT.getCode().equals(wmNews.getStatus())){
            //抽取内容和图片
            Map<String,Object> map = handleTextAndImages(wmNews);

            String contentText = (String) map.get("text");
            List<String> images = (List<String>) map.get("images");

            if (StringUtils.isNotBlank(contentText)){
                if (!handleTextScan(wmNews,contentText))
                    return;
            }

            if (images!=null&&!images.isEmpty()){
                if (!handleImagesScan(wmNews,images))
                    return;
            }

            if (StringUtils.isNotBlank(contentText)){
                if (!handleSensitive(wmNews,contentText))
                    return;
            }
            if (System.currentTimeMillis()>=wmNews.getPublishTime().getTime()) {
                saveAppArticle(wmNews);
            }else {
                updateWmNews(wmNews,(short)8,"审核通过");
            }

        }

    }

    private void saveAppArticle(WmNews wmNews) {
        ApArticle apArticle = saveArticle(wmNews);

        saveArticleConfig(apArticle);

        saveArticleContent(apArticle,wmNews);

        wmNews.setArticleId(apArticle.getId());
        updateWmNews(wmNews,(short)9,"文章发布");
        kafkaTemplate.send(ArticleForEsConstants.ARTICLE_ELASTICSEARCH_ADD,String.valueOf(apArticle.getId()));
    }

    private void saveArticleContent(ApArticle apArticle, WmNews wmNews) {
        ApArticleContent apArticleContent = new ApArticleContent();
        apArticleContent.setArticleId(apArticle.getId());
        apArticleContent.setContent(wmNews.getContent());
        articleFeign.saveArticleContent(apArticleContent);
    }

    private void saveArticleConfig(ApArticle apArticle) {
        ApArticleConfig apArticleConfig = new ApArticleConfig();
        apArticleConfig.setArticleId(apArticle.getId());
        apArticleConfig.setIsComment(true);
        apArticleConfig.setIsForward(true);
        apArticleConfig.setIsDown(false);
        apArticleConfig.setIsDelete(false);
        articleFeign.saveArticleConfig(apArticleConfig);
    }

    private ApArticle saveArticle(WmNews wmNews) {
        ApArticle apArticle = new ApArticle();
        apArticle.setTitle(wmNews.getTitle());
        apArticle.setLayout(wmNews.getType());
        apArticle.setFlag((byte)0);
        apArticle.setImages(wmNews.getImages());
        apArticle.setLabels(wmNews.getLabels());
        apArticle.setCreatedTime(new Date());
        apArticle.setPublishTime(wmNews.getPublishTime());

        Integer userId = wmNews.getUserId();
        WmUser wmUser = wemediaFeign.findWmUserById(Long.valueOf(userId));
        ApAuthor apAuthor = articleFeign.findAuthorByUserId(String.valueOf(wmUser.getApUserId()));
        if (apArticle!=null){
            apArticle.setAuthorId(Long.valueOf(apAuthor.getId()));
            apArticle.setAuthorName(apAuthor.getName());
        }
        AdChannel adChannel = adChannelMapper.selectById(wmNews.getChannelId());
        if (adChannel!=null){
            apArticle.setChannelId(adChannel.getId());
            apArticle.setChannelName(adChannel.getName());
        }
        return articleFeign.saveArticle(apArticle);
    }

    private boolean handleSensitive(WmNews wmNews, String contentText) {
        List<String> sensitive = adSensitiveMapper.findAllSensitive();
        SensitiveWordUtil.initMap(sensitive);
        Map<String, Integer> map = SensitiveWordUtil.matchWords(contentText);
        if (map!=null&&map.size()>0){
            updateWmNews(wmNews,(short)2,"文本中包含敏感词");
        }
        return true;
    }

    private boolean handleImagesScan(WmNews wmNews, List<String> images) {
        List<byte[]> list = new ArrayList<>();
        for (String image : images) {
            image= image.replace(url, "").trim();
            String group = image.substring(0, image.indexOf("/"));
            String path = image.substring(image.indexOf("/") + 1);
            try {
                list.add(fastDFSClient.download(group,path));
            } catch (IOException e) {
                e.printStackTrace();
                log.error("下载图片失败  group {} path {}",group,path);
            }
        }
        try {
            String suggestion = (String) greenImageScan.imageScan(list).get("suggestion");

            if (AuthConstants.AUTH_PASS.equals(suggestion))
                return true;
            if (AuthConstants.AUTH_REVIEW.equals(suggestion))
                updateWmNews(wmNews,(short)3,"图片中有不确定因素，需要人工审核");
            if (AuthConstants.AUTH_BLOCK.equals(suggestion))
                updateWmNews(wmNews,(short)2,"图片中有违规信息");

        } catch (Exception e) {
            log.error("进行图片审核时出错，{}",e.getMessage());
        }
        return false;
    }

    private boolean handleTextScan(WmNews wmNews, String contentText) {
        try {
            Map map = greenTextScan.greeTextScan(contentText);
            String suggestion = (String) map.get(AuthConstants.AUTH_SUGGESTION);
            if (AuthConstants.AUTH_PASS.equals(suggestion))
                return true;
            if (AuthConstants.AUTH_REVIEW.equals(suggestion))
                updateWmNews(wmNews,(short)3,"文本中有不确定因素，需要人工审核");
            if (AuthConstants.AUTH_BLOCK.equals(suggestion))
                updateWmNews(wmNews,(short)2,"文本中有违规信息");
        } catch (Exception e) {
            e.printStackTrace();
            log.error("进行文本审核时出错，出错的文章id为{}",wmNews.getId());
        }
        return false;
    }

    //修改news状态及reason方法
    private void updateWmNews(WmNews wmNews, short status, String reason) {
        wmNews.setStatus(status);
        wmNews.setReason(reason);
        wemediaFeign.updateWmNews(wmNews);
    }

    private Map<String, Object> handleTextAndImages(WmNews wmNews) {
        StringBuilder contentText= new StringBuilder(wmNews.getTitle()+"。");
        List<String> images = new ArrayList<>();
        List<Map> content = JSONArray.parseArray(wmNews.getContent(), Map.class);
        for (Map map : content) {
            if ("text".equals(map.get("type")))
                contentText.append((String) map.get("value"));
            if ("image".equals(map.get("type")))
                images.add((String) map.get("value"));
        }
        String coverImages = wmNews.getImages();
        if (wmNews.getType()!=0&&StringUtils.isNotBlank(coverImages)){
            images.addAll(Arrays.asList(coverImages.split(",")));
        }
        Map<String, Object> map = new HashMap<>();
        map.put("text",contentText.toString());
        map.put("images",images);
        return map;
    }

    @Override
    public ResponseResult findNews(NewsAuthDto dto) {
        if (dto==null)
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        ResponseResult responseResult = wemediaFeign.findList(dto);
        responseResult.setHost(url);
        return responseResult;
    }

    @Override
    public ResponseResult findOne(Integer id) {
        if (id==null)
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        WmNewsVo wmNewsVo = wemediaFeign.findWmNewsVo(id);
        ResponseResult responseResult = ResponseResult.okResult(wmNewsVo);
        responseResult.setHost(url);
        return responseResult;
    }

    @Override
    public ResponseResult updateStatus(Integer type, NewsAuthDto dto) {
        if (dto==null||dto.getId()==null)
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        WmNews wmNews = wemediaFeign.findById(dto.getId());
        if (wmNews==null)
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST,"该文章不存在");
        if (type==0)
            updateWmNews(wmNews,(short)2,dto.getMsg());
        if (type==1)
            updateWmNews(wmNews,(short)4,"人工审核通过");
        return ResponseResult.okResult();
    }
}
